package com.uinnova.product.eam.web.diagram.bean.impt;

import java.util.Collection;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.binary.core.util.BinaryUtils;
import com.binary.framework.Local;
import com.binary.framework.bean.User;
import com.binary.framework.exception.DubboException;
import com.binary.framework.exception.FrameworkException;
import com.binary.framework.exception.ServiceException;

public abstract class ProgressThread extends Thread {

    public abstract class Cycle<T extends Collection<E>, E> {

        public Cycle(T collection, Integer subNum) {
            this.collection = collection;
            if (0 != subNum)
                this.subNum = subNum;
            if (null != progressBean) {
                progressBean.setTotalRecords(collection.size());
            }
        }

        protected T collection;
        protected Integer subNum = 100;// 截取范围不能小于1

        public void init() {
            if (0 == collection.size())
                return;
            if (null != progressBean) {
                progressBean.resetProgressing(collection.size());
            }
            Iterator<E> iterator = collection.iterator();
            while (iterator.hasNext()) {
                int num = 0;
                before();
                for (; num < subNum && iterator.hasNext(); num++) {
                    E next = iterator.next();
                    toDoCycle(next);
                }
                After();
                if (null != progressBean) {
                    progressBean.progressing(num);
                }
            }
        }

        protected void before() {
        }

        protected abstract void toDoCycle(E item);

        protected void After() {
        }
    }

    public ProgressThread(User loginUser, ProgressBean progressBean) {
        this.loginUser = loginUser;
        this.progressBean = progressBean;
    }

    private static final Logger log = LoggerFactory.getLogger(ProgressThread.class);

    private User loginUser;
    private ProgressBean progressBean;

    @Override
    public void run() {

        log.info(" start new thread ... ");
        try {
            try {
                Local.open(loginUser);

                log.info(" start new thread successful. ");

                try {
                    toDo();
                    if (null != progressBean) {
                        progressBean.complete();
                    }

                } catch (Throwable e) {
                    if (null != progressBean) {
                        progressBean.err();
                    }
                    throw BinaryUtils.transException(e, ServiceException.class);
                } finally {
                    ProgressUtil.ciImporting = false;
                }

                try {
                    Local.commit();
                } catch (Exception ex) {
                    log.error(": Local.commit()出现错误!", ex);
                }
            } catch (Exception e) {
                try {
                    Local.rollback();
                } catch (Exception ex) {
                    log.error(": Local.rollback出现错误!", ex);
                }

                throw new FrameworkException(e);
            } finally {
                ProgressUtil.ciImporting = false;
                try {
                    Local.close();
                } catch (Exception ex) {
                    log.error(": Local.close()出现错误!", ex);
                }

            }
        } catch (Throwable e) {
            ProgressUtil.ciImporting = false;
            log.error("start new ProgressThread error!", e);
            throw BinaryUtils.transException(e, DubboException.class, "error start new ProgressThread.");
        }
    }

    @Override
    public synchronized void start() {
        this.setDaemon(true);
        super.start();
    }

    public abstract void toDo();

    protected ProgressBean getProgressBean() {
        return progressBean;
    }

    public void changeProgressBeanStatus(int status) {
        progressBean.setStatus(status);
    }

    public void changeProgressResultData(Object resultData) {
        progressBean.setResultData(resultData);
    }
}
